import { message } from "ant-design-vue";
import { noop } from "@/framework/util/warning.ts";
import type { ChildProcessReturn } from "@common/ipc-types.ts";

export interface WindowServiceInfo {
  name: string;
  state: string;
}

class WinSrv {
  static async query(serviceName: string): Promise<WindowServiceInfo[]> {
    try {
      const ret = await native.cp.execCmdTool("winsrv.exe", ["query", serviceName]);
      return ret.output
        .trim()
        .split(/[\r\n]/)
        .map(it => it.trim())
        .filter(it => !!it)
        .map(it => {
          const tokens = it.split("|");
          return {
            name: tokens[0].trim(),
            state: tokens[1].trim(),
          };
        });
    } catch (e) {
      console.error("[winsrv.query] error", e);
      return [];
    }
  }

  static async exists(serviceName: string): Promise<boolean> {
    const services = await WinSrv.query(serviceName);
    return services.some(v => v.name.toLowerCase() === serviceName.toLowerCase());
  }

  private static async _exec(action: string, serviceName: string): Promise<boolean> {
    try {
      const ret = await native.cp.execCmdToolSudo("winsrv.exe", [action, serviceName]);
      return ret.output.trim() === "1";
    } catch (e) {
      console.error(`[winsrv.${action}] error`, e);
      return false;
    }
  }

  static start(serviceName: string) {
    return WinSrv._exec("start", serviceName);
  }

  static stop(serviceName: string) {
    return WinSrv._exec("stop", serviceName);
  }

  static restart(serviceName: string) {
    return WinSrv._exec("restart", serviceName);
  }
}

class Envs {
  /**
   * 转换变量值,给百分号加上转义符
   * @param value
   */
  private static parseValue = (value: string) => {
    return value.replace(/%/g, "\\%");
  };

  private static setEnvCallback(res: ChildProcessReturn, show: boolean) {
    const [code, msg] = res.output.trim().split(",");
    if (show) {
      if (__DEV__) {
        if (res.errorOutput) console.error(res.errorOutput);
      }
      if (code === "1") {
        message.success("设置环境变量成功").then(noop);
      } else {
        message.error(msg || "设置环境变量失败").then(noop);
      }
    }
  }

  /**
   * 设置用户环境变量
   * @param name 变量名称
   * @param value 变量值
   * @param show 显示操作提示
   */
  static async setUserEnv(name: string, value: string, show = true) {
    if (__DEV__) console.log(`[setUserEnv] name=${name},value=${value}`);
    try {
      let res = await native.cp.execCmdTool("envs.exe", ["--name", name, "--value", Envs.parseValue(value)]);
      return Envs.setEnvCallback(res, show);
    } catch (e: any) {
      console.error(e);
      if (show) {
        message.error((e?.message ?? e?.toString()) || "设置环境变量失败").then(noop);
      }
    }
  }

  /**
   * 设置系统环境变量
   * @param name 变量名称
   * @param value 变量值
   * @param show 显示操作提示
   */
  static async setSystemEnv(name: string, value: string, show = true) {
    if (__DEV__) console.log(`[setSystemEnv] name=${name},value=${value}`);
    try {
      let res = await native.cp.execCmdToolSudo("envs.exe", ["--name", name, "--value", Envs.parseValue(value), "--machine"]);
      return Envs.setEnvCallback(res, show);
    } catch (e: any) {
      console.error(e);
      if (show) {
        message.error((e?.message ?? e?.toString()) || "设置环境变量失败").then(noop);
      }
    }
  }
}

/**
 * 命令行工具
 */
export const CmdTools = {
  /**
   * 环境变量工具
   */
  envs: Envs,
  /**
   * Windows服务工具
   */
  winsrv: WinSrv,
};
